﻿using Demo.Application.DbContexts;
using Demo.Application.Dtos.Dept;
using Demo.Application.Dtos.User;
using Demo.Domains.Entities.Sys;
using Mapster;
using Microsoft.Extensions.DependencyInjection;
using PmSoft.Core;
using PmSoft.Core.EventBus;
using PmSoft.Data.Abstractions;

namespace Demo.Application.Services.User;

[Inject(ServiceLifetime.Scoped)]
public class UserService
{
	private readonly IUnitOfWork unitOfWork;
	private readonly UserRepository userRepository;
	private readonly IServiceProvider serviceProvider;
	private readonly ICachedEntityLoader cachedEntityLoader;
	private readonly IEventBus eventBus;
	public UserService(IUnitOfWork unitOfWork,
		UserRepository userRepository,
		IServiceProvider serviceProvider,
		IEventBus eventBus,
		ICachedEntityLoader<AppDbContext> cachedEntityLoader)
	{
		this.unitOfWork = unitOfWork;
		this.userRepository = userRepository;
		this.serviceProvider = serviceProvider;
		this.eventBus = eventBus;
		this.cachedEntityLoader = cachedEntityLoader;
	}

	/// <summary>
	/// 创建用户
	/// </summary>
	/// <param name="form"></param>
	/// <returns></returns>
	/// <exception cref="Exception"></exception>
	public virtual async Task CreateAsync(UserCreateInput form)
	{
		var user = form.Adapt<SysUser>();
		await userRepository.InsertAsync(user);
		//await eventBus.PublishAsync(new UserCreatedEventArgs { });
		//eventBus.Publish(new UserCreatedEventArgs { });
		//eventBus.FireAndForget(new UserCreatedEventArgs { });
	}

	public async Task UpdateAsync(UserUpdateInput form)
	{
		var user = await userRepository.GetAsync(form.Id);
		if (user == null)
			throw new ArgumentNullException(nameof(user));

		//TypeAdapterConfig<UserUpdateInput, SysUser>.NewConfig().Ignore(dest => dest.Id);

		user = form.Adapt(user);
		await userRepository.UpdateAsync(user);
	}

	/// <summary>
	/// 获取单个用户
	/// </summary>
	/// <param name="id"></param>
	/// <returns></returns>
	/// <exception cref="ArgumentNullException"></exception>
	public async ValueTask<UserDto> GetUserAsync(int id)
	{
		var user = await userRepository.GetAsync(id);
		if (user == null)
			throw new ArgumentNullException(nameof(user));

		var userDto = user.Adapt<UserDto>();
		var dept = await cachedEntityLoader.GetEntityAsync<SysDept, int>(userDto.DeptId);
		userDto.Dept = dept.Adapt<DeptDto>();
		return userDto;
	}

	/// <summary>
	/// 获取单位下所有用户列表
	/// </summary>
	/// <param name="deptId"></param>
	/// <returns></returns>
	public async ValueTask<IEnumerable<UserDto>> GetUsersAsync(int deptId)
	{
		var users = await userRepository.GetUsersAsync(deptId);
		return await users.Select(user => user.Adapt<UserDto>())
			   .WithRelatedAsync(                                // 加载部门
				   foreignKeySelector: user => user.DeptId,
				   loadRelatedEntities: cachedEntityLoader.GetEntitiesByIdsAsync<SysDept, int>,
				   attachAction: (user, dept) => user.Dept = dept.Adapt<DeptDto>()
			   );
	}

	/// <summary>
	/// 用户分页列表
	/// </summary>
	/// <param name="pageIndex"></param>
	/// <param name="pageSize"></param>
	/// <returns></returns>
	public async ValueTask<IPagedList<UserDto>> UserPagingAsync(UserQuery query, int pageIndex = 1, int pageSize = 20)
	{
		var pagedUsers = await userRepository.UserPagingAsync(query, pageIndex, pageSize);

		return await pagedUsers
			.ToPagedDto(user => user.Adapt<UserDto>())   // 基础转换
			.WithRelatedAsync(                                // 加载部门
				foreignKeySelector: user => user.DeptId,
				loadRelatedEntities: cachedEntityLoader.GetEntitiesByIdsAsync<SysDept, int>,
				attachAction: (user, dept) => user.Dept = dept.Adapt<DeptDto>()
			);

	}

}
